package com.lesserpand.rabbitmq.netty.listener;

import com.lesserpand.rabbitmq.netty.NettySocketHolder;
import com.lesserpand.rabbitmq.netty.config.NettyConfig;
import com.lesserpand.rabbitmq.netty.constant.Constants;
import com.lesserpand.rabbitmq.netty.entity.SendMsgReqVO;
import com.lesserpand.rabbitmq.netty.utils.NettyServerInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;

/**
 * @author bailuo
 * @version 2.0
 * @Description TODO
 * @Date Created in 2019/1/22 14:40
 */
@Component
public class NettyServer {

    private static final Logger LOGGER = LoggerFactory.getLogger(NettyServer.class);

    /**
     * 创建bootstrap
     */
    private ServerBootstrap serverBootstrap = new ServerBootstrap();
    /**
     * BOSS
     */
    private EventLoopGroup boss = new NioEventLoopGroup();
    /**
     * Worker
     */
    private EventLoopGroup work = new NioEventLoopGroup();

    /**
     * NETT服务器配置类
     */
    @Resource
    private NettyConfig nettyConfig;

    /**
     * 关闭服务器方法
     */
    @PreDestroy
    public void close() {
        LOGGER.info("关闭服务器....");
        //优雅退出
        boss.shutdownGracefully();
        work.shutdownGracefully();
    }

    /**
     * 开启及服务线程
     */
    public void start() {
        // 从配置文件中(application.yml)获取服务端监听端口号
        int port = nettyConfig.getPort();
        try {
            //设置事件处理
            serverBootstrap.group(boss, work)
                    .channel(NioServerSocketChannel.class)
                    // 给服务端channel设置一些属性, 表示系统用于临时存放已完成三次握手的请求的队列的最大长度，如果连接建立频繁，服务器处理创建新连接较慢，可以适当调大这个参数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new NettyServerInitializer())
                    .localAddress(port);

            // 绑定端口,开始接收进来的连接
            ChannelFuture channelFuture = serverBootstrap.bind().sync();
            LOGGER.info("netty服务器在[{}]端口启动监听", port);
            // 等待服务器socket关闭
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            LOGGER.info("[出现异常] 释放资源");
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }

    public String sent(String msg) {
        LOGGER.info(msg);
        // 类似群发
        if (NettySocketHolder.getMAP().isEmpty()){
            return "没有客户端链接";
        }
        NettySocketHolder.getMAP().forEach((key, value) -> {
            NioSocketChannel socketChannel = NettySocketHolder.get(key);
            ByteBuf message = Unpooled.buffer(msg.getBytes().length);
            message.writeBytes(msg.getBytes());
            ChannelFuture future = socketChannel.writeAndFlush(message);
            future.addListener((ChannelFutureListener) channelFuture ->
                    LOGGER.info("客户端手动发消息成功={}", msg));
        });
        return "发送成功";
    }

}
